package cc.comac.saic.hkhy.jsrj.gj.inttools.service.impl;

import java.nio.file.Paths;
import java.util.List;

import org.gitlab4j.api.GitLabApiException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cc.comac.saic.hkhy.jsrj.gj.inttools.pojo.vo.ProjectDetailVO;
import cc.comac.saic.hkhy.jsrj.gj.inttools.dao.FileInfoDao;
import cc.comac.saic.hkhy.jsrj.gj.inttools.dao.FileVersionInfoDao;
import cc.comac.saic.hkhy.jsrj.gj.inttools.dao.ProjectInfoDao;
import cc.comac.saic.hkhy.jsrj.gj.inttools.entity.FileInfo;
import cc.comac.saic.hkhy.jsrj.gj.inttools.entity.FileVersionInfo;
import cc.comac.saic.hkhy.jsrj.gj.inttools.entity.ProjectInfo;
import cc.comac.saic.hkhy.jsrj.gj.inttools.entity.ProjectInfoItem;
import cc.comac.saic.hkhy.jsrj.gj.inttools.entity.ProjectRepoPath;
import cc.comac.saic.hkhy.jsrj.gj.inttools.gitlab.VersionManegeClient;
import cc.comac.saic.hkhy.jsrj.gj.inttools.service.ProjectInfoService;

/**
 * 项目信息(ProjectInfo)表服务实现类
 *
 * @author makejava
 * @since 2025-07-02 18:26:30
 */
@Service
public class ProjectInfoServiceImpl implements ProjectInfoService {

    @Value("${ini-tools.gitlab.nginx.relative.path:}")
    private String gitlabNginxRelativePath;

    @Autowired
    private ProjectInfoDao projectInfoDao;
    @Autowired
    private VersionManegeClient versionManegeClient;
    @Autowired
    private FileInfoDao fileInfoDao;
    @Autowired
    private FileVersionInfoDao fileVersionInfoDao;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public ProjectInfo queryById(Long id) {
        return this.projectInfoDao.queryById(id);
    }

    /**
     * 分页查询
     *
     * @param projectInfo 筛选条件
     * @return 查询结果
     */
    @Override
    public List<ProjectInfoItem> queryByCondition(ProjectInfo projectInfo) {
        /*
        modified by xbhlhs @ 2025-07-07
        to append repositories path
         */
        List<ProjectInfo> projectInfos = projectInfoDao.queryByCondition(projectInfo);
        return projectInfos.stream()
            .map(info -> {
                ProjectInfoItem item = new ProjectInfoItem();
                BeanUtils.copyProperties(info, item);
                ProjectRepoPath path = new ProjectRepoPath();
                path.setHlrModel(Paths.get(info.getProjKey(), gitlabNginxRelativePath, "hlr-model").toString());
                path.setHlrConsistency(Paths.get(info.getProjKey(), gitlabNginxRelativePath, "hlr-consistency").toString());
                path.setArchiModel(Paths.get(info.getProjKey(), gitlabNginxRelativePath, "archi-model").toString());
                path.setControlModel(Paths.get(info.getProjKey(), gitlabNginxRelativePath, "controller-model").toString());
                path.setDisplayModel(Paths.get(info.getProjKey(), gitlabNginxRelativePath, "display-model").toString());
                path.setControlCode(Paths.get(info.getProjKey(), gitlabNginxRelativePath, "controller-code").toString());
                path.setDisplayCode(Paths.get(info.getProjKey(), gitlabNginxRelativePath, "display-code").toString());
                path.setImplCode(Paths.get(info.getProjKey(), gitlabNginxRelativePath, "impl-code").toString());
                path.setTestCase(Paths.get(info.getProjKey(), gitlabNginxRelativePath, "test-case").toString());
                path.setStaticReport(Paths.get(info.getProjKey(), gitlabNginxRelativePath, "static-report").toString());
                path.setInstrCode(Paths.get(info.getProjKey(), gitlabNginxRelativePath, "instr-code").toString());
                path.setTestReport(Paths.get(info.getProjKey(), gitlabNginxRelativePath, "test-report").toString());
                item.setPath(path);
                return item;
            })
            .toList();
    }

    /**
     * 新增数据
     *
     * @param projectInfo 实例对象
     * @return 实例对象
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public ProjectInfo insert(ProjectInfo projectInfo) {
        // 检查项目名称是否为空
        if (projectInfo.getProjName() == null || projectInfo.getProjName().trim().isEmpty()) {
            throw new RuntimeException("项目名称不能为空");
        }

        // 检查项目key是否为空
        if (projectInfo.getProjKey() == null || projectInfo.getProjKey().trim().isEmpty()) {
            throw new RuntimeException("项目标识不能为空");
        }
        // 检查项目名称是否重复
        ProjectInfo nameCheck = new ProjectInfo();
        nameCheck.setProjName(projectInfo.getProjName());
        List<ProjectInfo> existingByName = this.projectInfoDao.queryByCondition(nameCheck);
        if (!existingByName.isEmpty()) {
            throw new RuntimeException("项目名称已存在: " + projectInfo.getProjName());
        }

        // 检查项目key是否重复
        ProjectInfo keyCheck = new ProjectInfo();
        keyCheck.setProjKey(projectInfo.getProjKey());
        List<ProjectInfo> existingByKey = this.projectInfoDao.queryByCondition(keyCheck);
        if (!existingByKey.isEmpty()) {
            throw new RuntimeException("项目标识已存在: " + projectInfo.getProjKey());
        }


        try {
            versionManegeClient.initProject(projectInfo.getProjKey(), projectInfo.getProjName());
        } catch (GitLabApiException e) {
            throw new RuntimeException(e);
        }

        this.projectInfoDao.insert(projectInfo);
        return projectInfo;
    }

    /**
     * 修改数据
     *
     * @param projectInfo 实例对象
     * @return 实例对象
     */
    @Override
    public ProjectInfo update(ProjectInfo projectInfo) {
        this.projectInfoDao.update(projectInfo);
        return this.queryById(projectInfo.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Long id) {
        return this.projectInfoDao.deleteById(id) > 0;
    }

    @Override
    public ProjectDetailVO getProjectDetail(Long projectId) {
        ProjectInfo project = this.projectInfoDao.queryById(projectId);
        if (project == null) return null;
        ProjectDetailVO vo = new ProjectDetailVO();
        vo.setId(project.getId());
        vo.setProjKey(project.getProjKey());
        vo.setProjName(project.getProjName());
        vo.setProjectCreateTime(project.getCreateTime());
        // 查询文件
        FileInfo fileInfoCond = new FileInfo();
        fileInfoCond.setProjId(projectId);
        List<FileInfo> fileInfos = fileInfoDao.queryByCondition(fileInfoCond);
        List<ProjectDetailVO.FileInfoVO> fileVOs = new java.util.ArrayList<>();
        for (FileInfo file : fileInfos) {
            ProjectDetailVO.FileInfoVO fileVO = new ProjectDetailVO.FileInfoVO();
            fileVO.setId(file.getId());
            fileVO.setFileKey(file.getFileKey());
            fileVO.setFilePath(file.getFilePath());
            fileVO.setFileType(file.getFileType());
            // 查询版本
            FileVersionInfo versionCond = new FileVersionInfo();
            versionCond.setFileInfoId(file.getId());
            List<FileVersionInfo> versions = fileVersionInfoDao.queryByCondition(versionCond);
            List<ProjectDetailVO.FileVersionInfoVO> versionVOs = new java.util.ArrayList<>();
            for (FileVersionInfo v : versions) {
                ProjectDetailVO.FileVersionInfoVO vvo = new ProjectDetailVO.FileVersionInfoVO();
                vvo.setId(v.getId());
                vvo.setVersion(v.getVersion());
                vvo.setHash(v.getHash());
                vvo.setVersionCreateTime(v.getCreateTime());
                versionVOs.add(vvo);
            }
            fileVO.setVersions(versionVOs);
            fileVOs.add(fileVO);
        }
        vo.setFiles(fileVOs);
        return vo;
    }

    @Override
    public boolean updateProjectInfo(Long projectId, String newName) {
        ProjectInfo project = this.projectInfoDao.queryById(projectId);
        if (project == null) return false;
        project.setProjName(newName);
        return this.projectInfoDao.update(project) > 0;
    }
}
